package com.scud.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.scud.client.system.ISystemClient;
import com.scud.common.constants.RedisConstants;
import com.scud.common.constants.SystemConstants;
import com.scud.common.error.ErrorConstants;
import com.scud.common.exception.ScudException;
import com.scud.common.utils.SecurityUtil;
import com.scud.model.PageResult;
import com.scud.model.cart.vo.CartItemVo;
import com.scud.model.cart.vo.CartSkuVo;
import com.scud.model.order.dto.FullOrderDto;
import com.scud.model.order.pojo.OrderDetails;
import com.scud.model.order.vo.ManageOrderVo;
import com.scud.model.order.vo.OrderSkuVo;
import com.scud.model.product.dto.ManagePageDto;
import com.scud.model.product.dto.ProductPageDto;
import com.scud.model.product.dto.SpecsSelectedDto;
import com.scud.model.product.pojo.*;
import com.scud.model.product.vo.ManageProductDetailsVo;
import com.scud.model.product.vo.ProductDetailsVo;
import com.scud.model.product.vo.ProductSkuVo;
import com.scud.product.mapper.CategoryMapper;
import com.scud.product.mapper.ProductMapper;
import com.scud.product.mapper.ProductSkuMapper;
import com.scud.product.mapper.ProductSpecMapper;
import com.scud.product.service.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Slf4j
public class ProductServiceImpl implements ProductService {
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private ProductSpecMapper productSpecMapper;
    @Autowired
    private ProductSkuMapper productSkuMapper;
    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ISystemClient systemClient;

    /**
     * 根据商品id获取商品详情
     * @param id
     * @return
     */
    @Override
    public ProductDetailsVo getProductDetails(Long id) {
        //获取商品基本信息
        Product product = productMapper.getById(id);
        //获取商品规格信息
        List<ProductSpec> specs = productSpecMapper.getSpecByProductId(id);
        //构造返回值
        ProductDetailsVo productDetailsVo = new ProductDetailsVo();
        BeanUtils.copyProperties(product, productDetailsVo);
        //转换成需要的格式
        /*Map<String, List<String>> spec = new HashMap<>();
        for (ProductSpec productSpec : specs) {
            spec.put(productSpec.getName(), productSpec.listOfValue());
        }*/
        List<SpecItem> spec = new ArrayList<>();
        for (ProductSpec productSpec : specs) {
            spec.add(new SpecItem(productSpec.getName(), productSpec.listOfValue()));
        }
        productDetailsVo.setSpec(spec);
        return productDetailsVo;
    }

    /**
     * 根据分类id进行条件分页查询
     * @param categoryId
     * @param productPageDto
     * @return
     */
    @Override
    public PageResult<Product> pageByCateId(Integer categoryId, ProductPageDto productPageDto) {
        productPageDto.setCategoryId(categoryId);
        Long total = productMapper.countByCategory(productPageDto);
        List<Product> list = productMapper.listByCategory(productPageDto);
        return new PageResult<>(total, list);
    }

    /**
     * 随机获取n件商品，返回当做轮播图
     * @return Result
     */
    @Override
    public List<Product> getBanner() {
        //准备初始数据结构
        int number = 0;
        List<Product> result = new ArrayList<>();
        Set<Long> idSet = new HashSet<>();
        Random random = new Random();
        //获取商品总数
        Long count = productMapper.count();

        while (number < SystemConstants.BANNER_NUM) {
            //随机获取一个商品id
            long targetId = random.nextLong(count);
            //判断id是否重复
            if (idSet.contains(targetId)) {
                continue;
            }
            idSet.add(targetId);
            //从数据库获取商品
            Product product = productMapper.selectById(targetId);
            //判断商品是否为空
            if (product == null) {
                continue;
            }
            //加入到结果集合当中
            result.add(product);
            number++;
        }
        return result;
    }

    /**
     * 获取一天内的新商品
     * @return
     */
    @Override
    public List<Product> getNew() {
        return productMapper.getNew();
    }

    /**
     * 获取首页最新商品
     * @return
     */
    @Override
    public List<Product> homeNew() {
        List<Product> list = productMapper.getNew();
        if (list.size() > SystemConstants.HOME_NEW_NUM) {
            list = list.subList(0, SystemConstants.HOME_NEW_NUM);
        }
        return list;
    }

    @Override
    public PageResult<Product> searchProduct(ProductPageDto dto) {
        //查询商品总数
        Long total = productMapper.count();
        //根据条件查询数据
        dto.setPage((dto.getPage() - 1) * dto.getPageSize());
        List<Product> list = productMapper.selectByQuery(dto);

        return new PageResult<>(total, list);
    }

    /**
     * 获取商品Sku的详情
     * @param ssd
     * @return
     */
    @Override
    public ProductSkuVo getSku(SpecsSelectedDto ssd) {
        return productSkuMapper.getSku(ssd);
    }

    /**
     * 扣减Sku的库存
     * @param skuIds
     */
    @Override
    public void deductStock(Map<Long, Integer> skuIds) {
        Set<Map.Entry<Long, Integer>> entries = skuIds.entrySet();
        for (Map.Entry<Long, Integer> entry : entries) {
            productSkuMapper.deductStock(entry.getKey(), entry.getValue());
        }
    }


    /**
     * 根据cartList中每个CartItemVo的skuId补全对应的sku信息
     * @param carList
     * @return
     */
    @Override
    public List<CartItemVo> getCartSku(List<CartItemVo> carList) {
        for (CartItemVo cartItemVo : carList) {
            ProductSku productSku = productSkuMapper.selectById(cartItemVo.getSkuId());
            String specText = productSku.getSpecText();
            List<SpecSelected> list = JSON.parseArray(specText, SpecSelected.class);
            Product product = productMapper.selectById(productSku.getProductId());
            cartItemVo.setCartSkuVo(new CartSkuVo(product.getName(), product.getImage(), list));
        }
        return carList;
    }

    /**
     * 恢复sku的库存
     * skuId = skuCount
     * @param skus
     */
    @Override
    public void resetStock(Map<String, Integer> skus) {
        Set<Map.Entry<String, Integer>> entries = skus.entrySet();
        for (Map.Entry<String, Integer> entry : entries) {
            Long skuId = Long.parseLong(entry.getKey());
            productSkuMapper.resetStock(skuId, entry.getValue());
        }
    }

    /**
     * 获取商品Sku相关信息
     * @param orderDetailsList:
     * @return List<OrderSkuVo>
     */
    @Override
    public List<OrderSkuVo> getOrderSkuVoList(List<OrderDetails> orderDetailsList) {
        List<OrderSkuVo> res = new ArrayList<>();

        for (OrderDetails orderDetails : orderDetailsList) {
            //从数据库中查询出相关数据
            ProductSku productSku = productSkuMapper.selectById(orderDetails.getSkuId());
            String specText = productSku.getSpecText();
            List<SpecSelected> list = JSON.parseArray(specText, SpecSelected.class);
            Product product = productMapper.selectById(productSku.getProductId());
            String image = product.getImage();
            //封装OrderSkuVo对象
            OrderSkuVo vo = new OrderSkuVo();
            vo.setSkuId(productSku.getId());
            vo.setName(product.getName());
            vo.setTotal(orderDetails.getCount());
            vo.setImage(image);
            vo.setSpec(list);
            //添加到返回集合当中
            res.add(vo);
        }
        return res;
    }

    /**
     * 商家商品分页列表查询
     * @param dto:
     * @return Result
     */
    @Override
    public PageResult<Product> manageProductPage(ManagePageDto dto) {
        //获取发起本次请求的商家用户id
        Long userId = SecurityUtil.getUser().getId();
        //查询当前商家的商品总数
        Long total = productMapper.countByUserId(userId);
        //根据条件在数据库中查询相关数据
        dto.setPage((dto.getPage() - 1) * dto.getPageSize());
        List<Product> productList = productMapper.selectByUserIdQuery(dto, userId);
        //封装PageResult对象，并返回
        PageResult<Product> pageResult = new PageResult<>();
        pageResult.setTotal(total);
        pageResult.setList(productList);
        return pageResult;
    }

    /**
     * 根据商品id获取商品详情
     * @param id:
     * @return Result
     */
    @Override
    public ManageProductDetailsVo getManageDetails(Long id) {
        //获取当前用户id
        Long userId = SecurityUtil.getUser().getId();
        //查询商品的基本信息
        Product product = productMapper.selectById(id);
        if (product == null) {
            throw new ScudException(ErrorConstants.PRODUCT_NOT_EXISTS);
        }
        if (!product.getUserId().equals(userId)) {
            throw new ScudException(ErrorConstants.PRODUCT_NOT_EXISTS);
        }
        //根据商品的分类id查询商品分类名称
        Category category = categoryMapper.selectById(product.getCategoryId());
        //查询商品的规格信息，封装成相应格式
        List<ProductSpec> specList = productSpecMapper.getSpecByProductId(id);
        ArrayList<SpecItem> specItems = new ArrayList<>();
        for (ProductSpec productSpec : specList) {
            SpecItem specItem = new SpecItem();
            specItem.setName(productSpec.getName());
            specItem.setValue(productSpec.listOfValue());
            specItems.add(specItem);
        }
        //查询商品的SKU信息
        List<ProductSku> skus = productSkuMapper.selectByProductId(id);
        for (ProductSku sku : skus) {
            List<SpecSelected> selectedSpecs = JSON.parseArray(sku.getSpecText(), SpecSelected.class);
            sku.setSelectedSpecs(selectedSpecs);
        }
        //封装返回对象
        ManageProductDetailsVo vo = new ManageProductDetailsVo();
        BeanUtils.copyProperties(product, vo);
        vo.setSpecs(specItems);
        vo.setSkus(skus);
        vo.setCategory(category.getName());
        return vo;
    }


    /**
     * 修改商品信息
     * @param dto:
     * @return Result
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProduct(ManageProductDetailsVo dto) {
        //根据商品id查询商品得到用户id，校验所属关系
        Long userId = SecurityUtil.getUser().getId();
        Long productId = dto.getId();

        if (productId!=null && !userId.equals(productMapper.selectById(productId).getUserId())) {
            throw new ScudException(ErrorConstants.USER_ILL_LEGAL);
        }
        //检查商品规格与商品SKU信息是否符合要求
        if (dto.getSpecs() == null || dto.getSpecs().size() == 0) {
            throw new ScudException(ErrorConstants.PRODUCT_SPEC_ERROR);
        }
        List<String> specNames = dto.getSpecs().stream().map(SpecItem::getName).toList();
        String flagSpec = spliceList(specNames);
        //校验每一组Sku
        List<ProductSku> skuList = dto.getSkus();
        if (skuList==null ||skuList.size()==0){
            throw new ScudException(ErrorConstants.PRODUCT_SKU_NULL);
        }
        double minPrice = Double.MAX_VALUE;
        for (ProductSku productSku : skuList) {
            minPrice=Math.min(minPrice,productSku.getPrice());
            List<String> skuNameList = productSku.getSelectedSpecs().stream().map(SpecSelected::getName).toList();
            String skuName = spliceList(skuNameList);
            if (!skuName.equals(flagSpec)) {
                throw new ScudException(ErrorConstants.PRODUCT_SPEC_ERROR);
            }
        }

        //修改product表中的数据
        Product product = new Product();
        BeanUtils.copyProperties(dto, product);
        //查询分类id
        Integer categoryId = categoryMapper.selectByName(dto.getCategory()).getId();
        product.setCategoryId(categoryId);
        product.setMinPrice(minPrice);
        if (productId==null){
            //商家新增商品
        product.setUserId(userId);
            productMapper.insert(product);
            productId=product.getId();
        }else {
            //修改商品
            productMapper.update(product);
        }

        //修改product_spec表中的数据
        //先删除相关规格，再将规格插入到数据库当中
        productSpecMapper.deleteByProductId(productId);
        List<SpecItem> specs = dto.getSpecs();
        List<ProductSpec> productSpecList = new ArrayList<>();
        Long tempProductId = productId;
        specs.forEach(specItem -> {
            ProductSpec productSpec = new ProductSpec();
            BeanUtils.copyProperties(specItem, productSpec);
            productSpec.setProductId(tempProductId);
            productSpec.setValue(specItem.getValue().toString());
            productSpecList.add(productSpec);
        });
        productSpecMapper.insertList(productSpecList);
        //修改product_sku表中的数据,同上
        productSkuMapper.deleteByProductId(productId);

        skuList.forEach(sku -> {
            sku.setSpecText(JSON.toJSONString(sku.getSelectedSpecs()));
            sku.setProductId(tempProductId);
        });
        productSkuMapper.insertList(skuList);
        //设置redis当中的库存
        List<ProductSku> productSkuStock = productSkuMapper.selectByProductId(productId);
        for (ProductSku productSku : productSkuStock) {
            stringRedisTemplate.opsForValue().set(RedisConstants.SKU+productSku.getId(),productSku.getStock().toString());
        }
    }

    /**
     * 将字符串集合按照字典序拼接成一个字符串
     * @param stringList:
     * @return String
     */
    private String spliceList(List<String> stringList) {
        ArrayList<String> list = new ArrayList<>(stringList);
        Collections.sort(list);
        log.info("经过字典排序过后的商品规格名称集合为:{}", list);
        //拼接字符串
        StringBuilder sb = new StringBuilder();
        list.forEach(sb::append);
        log.info("拼接后的标志字符串为:{}", sb.toString());
        return sb.toString();
    }

    /**
     * 商家根据商品id删除商品
     * @param productId:
     * @return Result
     * @author vermouth
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteProduct(Long productId) {
        //删除商品基本信息
        productMapper.deleteById(productId);
        //删除商品规格信息
        productSpecMapper.deleteByProductId(productId);
        //删除商品SKU信息
        productSkuMapper.deleteByProductId(productId);
    }

    /**
     * 修改商品上下架状态
     * @param productId:
     * @param status:
     * @return Result
     */
    @Override
    public void updateStatus(Long productId, Short status) {
        //判断状态是否为0,2
        if (!status.equals((short)0) && !status.equals((short)2)){
            throw new ScudException(ErrorConstants.STATUS_ERROR);
        }
        //修改数据库中的数据状态
        productMapper.updateStatus(productId,status);
    }

    /**
     * 完善orderDto的信息
     * @param orderDto
     * @return
     */
    @Override
    public FullOrderDto completeInfo(FullOrderDto orderDto) {
        //填入订单总金额
        Map<Long, Integer> skuCount = orderDto.getSkuCount();
        Double total = calculateCost(skuCount);
        orderDto.getOrder().setTotal(total);
        //完善orderDetails中的商家id
        List<OrderDetails> orderDetails = orderDto.getOrderDetails();
        orderDetails.forEach(od -> {
            Long userId = productSkuMapper.getMerchantId(od.getSkuId());
            od.setUserId(userId);
        });
        orderDto.setOrderDetails(orderDetails);
        return orderDto;
    }

    /**
     * 计算订单总金额
     * @param skuCount
     * @return
     */
    public Double calculateCost(Map<Long, Integer> skuCount) {
        double total = 0.0;
        Set<Map.Entry<Long, Integer>> entries = skuCount.entrySet();
        for (Map.Entry<Long, Integer> entry : entries) {
            ProductSku productSku = productSkuMapper.selectById(entry.getKey());
            total = total + productSku.getPrice() * entry.getValue();
        }
        return total;
    }

    /**
     * 获取商家所需要的订单商品信息
     * @param orderDetailsList:
     * @return List<ManageOrderVo>
     * @author vermouth
     */
    @Override
    public List<ManageOrderVo> getManageOrderPage(List<ManageOrderVo> orderDetailsList) {

        List<ManageOrderVo> voList = new ArrayList<>();

        for (ManageOrderVo orderDetails : orderDetailsList) {
            Long skuId = orderDetails.getSkuId();
            //查询相关信息
            ProductSku productSku = productSkuMapper.selectById(skuId);
            Product product = productMapper.selectById(productSku.getProductId());
            //封装对象
            ManageOrderVo vo = new ManageOrderVo();
            BeanUtils.copyProperties(orderDetails,vo);
            vo.setProductSpec(productSku.getSpecText());
            vo.setProductName(product.getName());
            voList.add(vo);
        }
        return voList;
    }
}
